package com.hxzy.controller;

import lombok.extern.log4j.Log4j2;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Log4j2
@RestController
public class OrderController {

    /**
     * 数据库的值
     */
    public static final String CREATE_ORDER_KEY="db:order:";



    @Autowired
    private RedisTemplate redisTemplate;


    @Autowired
    private RabbitTemplate rabbitTemplate;


    /**
     * 创建订单
     * @return
     */
    @GetMapping(value = "/create/order")
    public Map<String,Object> createOrder(){
        Map<String,Object>   map=new HashMap<>();
        map.put("id",1000000);
        map.put("user_id",1111);
        map.put("money",20);
        //未支付
        map.put("pay",0);
        map.put("pay_time","");
        map.put("create_time",new Date());

        String redisKey=CREATE_ORDER_KEY+map.get("id").toString();
        this.redisTemplate.opsForValue().set(redisKey, map);

        //向mq中发送订单消息，延迟1分钟
        this.rabbitTemplate.convertAndSend("delay.order.direct","delay",map.get("id").toString());


        return map;
    }

    /**
     * 点击订单，手动支付订单
     * @param orderId
     * @return
     */
    @GetMapping(value = "/pay/{id}")
    public String payOrder(@PathVariable(value = "id") String orderId){

        //加入分布式锁（最简单的，最不可靠的）
        String lockKey = "lock:order:" + orderId;

        String redisKey=CREATE_ORDER_KEY+ orderId;

        Object redisValue = this.redisTemplate.opsForValue().get(redisKey);

        try {
            if (Objects.nonNull(redisValue)) {
                //加入分布式锁

                //加入分布式锁，如果超过1分钟，自定义释放
                if (!this.redisTemplate.opsForValue().setIfAbsent(lockKey, 0, 60, TimeUnit.SECONDS)) {
                    throw new RuntimeException("多线程操作同一笔订单，支付失败的");
                }


                Map<String, Object> map = (Map<String, Object>) redisValue;

                if (map.get("pay").equals(1)) {
                    throw new RuntimeException("已经支付过了，不要再支付了");
                }

                //调用支付流程

                map.put("pay", 1);
                map.put("pay_time", new Date());
                this.redisTemplate.opsForValue().set(redisKey, map);

                Thread.sleep(20*1000);

                log.info(orderId + ",支付成功了");

            } else {
                throw new RuntimeException("未找到订单信息，不允许支付");
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            //手动释放锁
            this.redisTemplate.delete(lockKey);
        }
        return  orderId+",支付成功";
    }



}
